package com.songlanyun.modules.account.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.songlanyun.common.enums.LockPrefixConstant;
import com.songlanyun.common.enums.MemberConstant;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.modules.exception.MemberException;
import com.songlanyun.modules.shop.entity.ShopUserRoleConfigEntity;
import com.songlanyun.modules.shop.service.ShopUserRoleConfigService;
import org.apache.commons.lang.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import java.util.concurrent.TimeUnit;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.songlanyun.modules.account.dao.UserShopRoleDao;
import com.songlanyun.modules.account.entity.UserShopRoleEntity;
import com.songlanyun.modules.account.service.UserShopRoleService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;


@Service("yxtUserShopRoleService")
public class UserShopRoleServiceImpl extends ServiceImpl<UserShopRoleDao, UserShopRoleEntity> implements UserShopRoleService {

    @Resource
    private UserShopRoleDao userShopRoleDao;

    @Resource
    private ShopUserRoleConfigService shopUserRoleConfigService;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 根据条件查询会员等级设置
     *
     * @return
     */
    @Override
    public List<UserShopRoleEntity> getList(UserShopRoleEntity entity) {
        List<UserShopRoleEntity> list = userShopRoleDao.selectList(
                new LambdaQueryWrapper<UserShopRoleEntity>()
                        .eq(entity.getUserId() != null, UserShopRoleEntity::getUserId, entity.getUserId())//会员id
                        .eq(entity.getShopId() != null, UserShopRoleEntity::getShopId, entity.getShopId())//商铺id
                        .eq(StringUtils.isNotBlank(entity.getRoleCode()), UserShopRoleEntity::getRoleCode, entity.getRoleCode())// 用户在当前商家店的会员等级编号
                        .eq(StringUtils.isNotBlank(entity.getRoleName()), UserShopRoleEntity::getRoleName, entity.getRoleName())//用户在当前商家店的会员等级名
                        .eq(entity.getLevel() != null, UserShopRoleEntity::getLevel, entity.getLevel())//等级
                        .orderByAsc(UserShopRoleEntity::getLevel)
        );
        return list;
    }

    @Override
    public UserShopRoleEntity getUserShopRole(Long shopId, Long userId) {
        UserShopRoleEntity one = this.getOne(
                new LambdaQueryWrapper<UserShopRoleEntity>()
                        .eq(UserShopRoleEntity::getShopId, shopId)
                        .eq(UserShopRoleEntity::getUserId, userId)
                        .last("limit 1"));
        return one;
    }

    /**
     * 更新金额
     *
     * @param userId
     * @param shopId
     * @param amount
     * @return
     */
    @Override
    public UserShopRoleEntity updateAmount(Long userId, Long shopId, BigDecimal amount) {
        //查询该会员在当前店铺中的等级记录
        UserShopRoleEntity userShopRole = this.getUserShopRole(shopId, userId);
        //如果为空的话，该会员需要在该店铺初始化一条记录
        if (userShopRole == null) {
            userShopRole = this.init(userId, shopId, MemberConstant.MemberLevel.GENERAL.getCode(), amount);
        } else {
            //增加总消费
            userShopRole = addAmount(userShopRole.getId(), amount);
        }


        return userShopRole;
    }

    /**
     * 根据等级初始化一条等级记录
     *
     * @param userId
     * @param shopId
     * @return
     */
    @Override
    public UserShopRoleEntity init(Long userId, Long shopId, Integer level, BigDecimal amount) {
        //根据等级查询该店铺下的等级信息
        ShopUserRoleConfigEntity configEntity = shopUserRoleConfigService.getByShopIdAndLevel(shopId, level);

        UserShopRoleEntity userShopRoleEntity = new UserShopRoleEntity();
        userShopRoleEntity.setUserId(userId);
        userShopRoleEntity.setShopId(shopId);
        userShopRoleEntity.setLevel(level);
        userShopRoleEntity.setRoleCode(configEntity.getRoleCode());
        userShopRoleEntity.setRoleName(configEntity.getOuterRoleName());
        userShopRoleEntity.setTotalConsumption(amount);//总消费初始化
        this.save(userShopRoleEntity);
        return userShopRoleEntity;
    }

    @Override
    public BigDecimal getSumByUserId(Long userId) {
        return this.baseMapper.getSumByUserId(userId);
    }

    @Override
    public BigDecimal getSumByUserIdAndShopId(Long userId, Long shopId) {
        return this.baseMapper.getSumByUserIdAndShopId(userId, shopId);
    }


    /**
     * 更新金额
     *
     * @return
     */
    private UserShopRoleEntity addAmount(Long id, BigDecimal amount) {
        RLock lock = redissonClient.getLock(LockPrefixConstant.USER_TOTAL_CONSUMPTION + id);
        lock.lock(2, TimeUnit.SECONDS);
        UserShopRoleEntity entity = null;
        try {
            entity = this.getById(id);
            entity.addTotalConsumption(amount);
            this.updateById(entity);
        } finally {
            lock.unlock();
        }
        return entity;
    }

    /**
     * 更新某用户在某店铺中的会员等级
     *
     * @param userId
     * @param shopId
     * @param level
     */
    @Override
    public void updateLevelByUserAndShop(Long userId, Long shopId, Integer level) {
        //会员在店铺的等级记录
        UserShopRoleEntity userShopRoleEntity = getUserShopRole(shopId, userId);

        //修改等级
        if (userShopRoleEntity != null) {
            //根据等级查询该店铺下的等级信息
            ShopUserRoleConfigEntity byShopIdAndLevel = shopUserRoleConfigService.getByShopIdAndLevel(shopId, level);
            userShopRoleEntity.setLevel(level);
            userShopRoleEntity.setRoleCode(byShopIdAndLevel.getRoleCode());
            userShopRoleEntity.setRoleName(byShopIdAndLevel.getRoleName());
            this.updateById(userShopRoleEntity);
        } else {
            //如果在商家下没有记录，则生成一条新的记录
            //查询该店铺该等级下的会员等级设置
            this.init(userId, shopId, level, BigDecimal.ZERO);
        }
    }

    /**
     * 克隆会员等级记录（根据推荐的所有会员id和该会员的所属店铺id生成会员等级记录）
     *
     * @param ids              需克隆的记录
     * @param subjectionShopId 该会员的所属id
     * @param shopId           该会员的商家id
     */
    @Override
    public void saveByAccountAndShop(List<Long> ids, Long subjectionShopId, Long shopId) {
        //查询需克隆的记录
        List<UserShopRoleEntity> list = getListByIdsAndShopId(ids, subjectionShopId);

        //如果没有记录，就不用克隆
        //保存
        list.forEach(v -> {
            copyRole(v, shopId);//拷贝等级
        });
    }


    @Override
    public void saveAndUpdateByIdsAndShop(List<Long> ids, Long subjectionShopId, Long shopId) {
        //查询需克隆的记录
        List<UserShopRoleEntity> list = getListByIdsAndShopId(ids, subjectionShopId);

        for (UserShopRoleEntity role : list) {
            //查询在现在商家有没有过记录
            UserShopRoleEntity newRole = getUserShopRole(shopId, role.getUserId());
            if (newRole != null) {
                //在现在商家有过记录
                //如果现在的会员等级大于之前的，则无需更新
                if (newRole.getLevel() < role.getLevel()) {
                    //如果现在的会员等级小于之前的，则更新,消费不变
                    newRole.setShopId(shopId);//设置所属商家id
                    newRole.setLevel(role.getLevel());//拷贝等级
                    newRole.setRoleName(role.getRoleName());
                    newRole.setRoleCode(role.getRoleCode());
                    this.baseMapper.updateById(newRole);
                }
            } else {
                //没有记录,拷贝等级
                copyRole(role, shopId);
            }
        }
    }

    @Transactional
    @Override
    public void updateClass(Long shopId, Long userId, Integer level) {
        //不能修改市代的等级
        UserShopRoleEntity userShopRole = this.getUserShopRole(shopId, userId);
        if (ObjectUtil.isNull(userShopRole)) {
            this.init(userId, shopId, level, new BigDecimal("0"));
        } else {

            if (MemberConstant.MemberLevel.CITY_AGENT.getCode().equals(userShopRole.getLevel())) {
                throw new RRException(MemberException.AGE_LEVELS_CANNOT_BE_MODIFIED);
            }
            //查询配置
            ShopUserRoleConfigEntity config = shopUserRoleConfigService.getByShopIdAndLevel(shopId, level);

            userShopRole.setLevel(config.getLevel());
            userShopRole.setRoleCode(config.getRoleCode());
            userShopRole.setRoleName(config.getOuterRoleName());
            userShopRoleDao.updateById(userShopRole);
        }

    }

    /**
     * 拷贝等级
     *
     * @param role
     * @param shopId
     */
    private void copyRole(UserShopRoleEntity role, Long shopId) {
        UserShopRoleEntity newRole = new UserShopRoleEntity();
        role.setId(null);
        BeanUtils.copyProperties(role, newRole);//将记录拷贝一份保存
        newRole.setShopId(shopId);//设置所属商家id
        newRole.setTotalConsumption(BigDecimal.ZERO);//将总消费初始化零
        this.save(newRole);
    }

    private List<UserShopRoleEntity> getListByIdsAndShopId(List<Long> ids, Long shopId) {
        //查询需克隆的记录
        return this.baseMapper.selectList(
                new LambdaQueryWrapper<UserShopRoleEntity>()
                        .eq(UserShopRoleEntity::getShopId, shopId)
                        .in(UserShopRoleEntity::getUserId, ids)
        );
    }


}
